home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / agrep / preprocess.c < prev    next >
C/C++ Source or Header  |  1995-05-16  |  9KB  |  345 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* substitute metachar with special symbol                               */
  3. /* if regularr expression, then set flag REGEX                           */
  4. /* if REGEX and MULTIPAT then report error message,                      */
  5. /* -w only for single word pattern. If WORDBOUND & MULTIWORD error       */
  6. /* process start of line, endof line symbol,                             */
  7. /* process -w WORDBOUND option, append special symbol at begin&end of    */
  8. /* process -d option before this routine                                 */
  9. /* the delimiter pattern is in D_pattern (need to end with '; ')         */
  10. /* if '-t' (suggestion: how about -B) the pattern is passed to sgrep     */
  11. /* and doesn't go here                                                   */
  12. /* in that case, -d is ignored? or not necessary                         */
  13. /* upon return, Pattern contains the pattern to be processed by maskgen  */
  14. /* D_pattern contains transformed D_pattern                              */
  15.  
  16. #include "agrep.h"
  17.  
  18. extern int PAT_FILE, PAT_BUFFER;
  19. extern ParseTree *AParse;
  20. extern int WHOLELINE, REGEX, RE_ERR, DELIMITER, TAIL, WORDBOUND;
  21. extern int HEAD;
  22. extern CHAR Progname[];
  23. extern int D_length, tc_D_length;
  24. extern CHAR tc_D_pattern[MaxDelimit * 2];
  25. extern int table[WORD][WORD];
  26. extern int agrep_initialfd;
  27. extern int EXITONERROR;
  28. extern int errno;
  29.  
  30. extern int  multifd;
  31. extern char *multibuf;
  32. extern int  multilen;
  33. extern int anum_terminals;
  34. extern ParseTree aterminals[MAXNUM_PAT];
  35. extern char FREQ_FILE[MAX_LINE_LEN], HASH_FILE[MAX_LINE_LEN], STRING_FILE[MAX_LINE_LEN];    /* interfacing with tcompress */
  36. extern int AComplexBoolean;
  37.  
  38. preprocess(D_pattern, Pattern)   /* need two parameters  */
  39. CHAR D_pattern[], Pattern[];
  40. {
  41.     CHAR temp[Maxline], *r_pat, *old_pat;  /* r_pat for r.e. */
  42.     CHAR old_D_pat[MaxDelimit];
  43.     int i, j=0, rp=0, m, t=0, num_pos, ANDON = 0;
  44.     int d_end ;  
  45.     int IN_RANGE=0;
  46.     int ret1, ret2;
  47.  
  48. #if    DEBUG
  49.     fprintf(stderr, "preprocess: m=%d, pat=%s, PAT_FILE=%d, PAT_BUFFER=%d\n", strlen(Pattern), Pattern, PAT_FILE, PAT_BUFFER);
  50. #endif
  51.     if ((m = strlen(Pattern)) <= 0) return 0;
  52.     if (PAT_FILE || PAT_BUFFER) return 0;
  53.     REGEX = OFF;
  54.     old_pat = Pattern; /* to remember the starting position */
  55.  
  56.     /* Check if pattern is a concatenation of ands OR ors of simple patterns */
  57.     multibuf = (char *)malloc(m * 2 + 2);    /* worst case: a,a,a,a,a,a */
  58.     if (multibuf == NULL) goto normal_processing;
  59.     /* if (WORDBOUND) goto normal_processing; */
  60.  
  61.     multilen = 0;
  62.     AParse = 0;
  63.     ret1 = ret2 = 0;
  64.     if (((ret1 = asplit_pattern(Pattern, m, aterminals, &anum_terminals, &AParse)) <= 0) ||    /* can change the pattern if simple boolean with {} */
  65.         ((ret2 = asplit_terminal(0, anum_terminals, multibuf, &multilen)) <= 1)) {    /* must do normal processing */
  66.         if (AComplexBoolean && (AParse != NULL)) destroy_tree(AParse);    /* so that direct exec invocations don't use AParse by mistake! */
  67. #if    DEBUG
  68.         fprintf(stderr, "preprocess: split_pat = %d, split_term = %d, #terms = %d\n", ret1, ret2, anum_terminals);
  69. #endif    /*DEBUG*/
  70.         /*
  71.         if (ret2 == 1) {
  72.             strcpy(Pattern, aterminals[0].data.leaf.value);
  73.             m = strlen(Pattern);
  74.         }
  75.         */
  76.         m = strlen(Pattern);
  77.         AParse = 0;
  78.         free(multibuf);
  79.         multibuf = NULL;
  80.         multilen = 0;
  81.         goto normal_processing;
  82.     }
  83.  
  84.     /* This is quick processing */
  85.     if (AParse != 0) {    /* successfully converted to ANDPAT/ORPAT */
  86.         PAT_BUFFER = 1;
  87.         /* printf("preprocess(): converted= %d, patterns= %s", AParse, multibuf); */
  88.         /* Now I have to process the delimiter if any */
  89.         if (DELIMITER) {
  90.             /* D_pattern is "<PAT>; ", D_length is 1 + length of string PAT: see agrep.c/'d' */
  91.             preprocess_delimiter(D_pattern+1, D_length - 1, D_pattern, &D_length);
  92.             /* D_pattern is the exact stuff we want to match, D_length is its strlen */
  93.             if ((tc_D_length = quick_tcompress(FREQ_FILE, HASH_FILE, D_pattern, D_length, tc_D_pattern, MaxDelimit*2, TC_EASYSEARCH)) <= 0) {
  94.                 strcpy(tc_D_pattern, D_pattern);
  95.                 tc_D_length = D_length;
  96.             }
  97.             /* printf("mgrep's delim=%s,%d tc_delim=%s,%d\n", D_pattern, D_length, tc_D_pattern, tc_D_length); */
  98.         }
  99.         return 0;
  100.     }
  101.     /* else either unknown character, one simple pattern or none at all */
  102.  
  103. normal_processing:
  104.     for(i=0; i< m; i++) {
  105.         if(Pattern[i] == '\\') i++;
  106.         else if(Pattern[i] == '|' || Pattern[i] == '*') REGEX = ON;
  107.     }
  108.  
  109.     r_pat = (CHAR *) malloc(strlen(Pattern)+2*strlen(D_pattern) + 8);    /* bug-report, From: Chris Dalton <crd@hplb.hpl.hp.com> */
  110.     strcpy(temp, D_pattern);
  111.     d_end = t = strlen(temp);  /* size of D_pattern, including '; ' */
  112.     if (WHOLELINE) { 
  113.         temp[t++] = LANGLE; 
  114.         temp[t++] = NNLINE; 
  115.         temp[t++] = RANGLE;
  116.         temp[t] = '\0';
  117.         strcat(temp, Pattern);
  118.         m = strlen(temp);
  119.         temp[m++] = LANGLE; 
  120.         temp[m++] = '\n'; 
  121.         temp[m++] = RANGLE; 
  122.         temp[m] = '\0';  
  123.     }
  124.     else {
  125.         if (WORDBOUND) { 
  126.             temp[t++] = LANGLE; 
  127.             temp[t++] = WORDB; 
  128.             temp[t++] = RANGLE;
  129.             temp[t] = '\0'; 
  130.         }
  131.         strcat(temp, Pattern);
  132.         m = strlen(temp);
  133.         if (WORDBOUND) { 
  134.             temp[m++] = LANGLE; 
  135.             temp[m++] = WORDB; 
  136.             temp[m++] = RANGLE; 
  137.         }
  138.         temp[m] = '\0';
  139.     }
  140.     /* now temp contains augmented pattern , m it's size */
  141.     D_length = 0;
  142.     for (i=0, j=0; i< d_end-2; i++) {
  143.         switch(temp[i]) 
  144.         {
  145.         case '\\' : 
  146.             i++; 
  147.             Pattern[j++] = temp[i];
  148.             old_D_pat[D_length++] = temp[i];
  149.             break;
  150.         case '<'  : 
  151.             Pattern[j++] = LANGLE;
  152.             break;
  153.         case '>'  : 
  154.             Pattern[j++] = RANGLE;
  155.             break;
  156.         case '^'  : 
  157.             Pattern[j++] = '\n';
  158.             old_D_pat[D_length++] = temp[i];
  159.             break;
  160.         case '$'  : 
  161.             Pattern[j++] = '\n';
  162.             old_D_pat[D_length++] = temp[i];
  163.             break;
  164.         default  :  
  165.             Pattern[j++] = temp[i];
  166.             old_D_pat[D_length++] = temp[i];
  167.             break;
  168.         }
  169.     }
  170.     if(D_length > MAXDELIM) {
  171.         fprintf(stderr, "%s: delimiter pattern too long (has > %d chars)\n", Progname, MAXDELIM);
  172.         free(r_pat);
  173.         if (!EXITONERROR) {
  174.             errno = 2;
  175.             return -1;
  176.         }
  177.         else exit(2);
  178.     }
  179.  
  180.     Pattern[j++] = ANDPAT;
  181.     old_D_pat[D_length] = '\0';
  182.     strcpy(D_pattern, old_D_pat);
  183.     D_length++;
  184.     /*
  185.       Pattern[j++] = ' ';
  186.     */
  187.     Pattern[j] = '\0';
  188.     rp = 0; 
  189.     if(REGEX) {
  190.         r_pat[rp++] = '.';    /* if REGEX: always append '.' in front */
  191.         r_pat[rp++] = '(';
  192.         Pattern[j++] = NOCARE;
  193.         HEAD = ON;
  194.     }
  195.     for (i=d_end; i < m ; i++)
  196.     {
  197.         switch(temp[i]) 
  198.         {
  199.         case '\\': 
  200.             i++;  
  201.             Pattern[j++] = temp[i]; 
  202.             r_pat[rp++] = 'o';   /* the symbol doesn't matter */
  203.             break;
  204.         case '#':  
  205.             if(REGEX) {
  206.                 Pattern[j++] = NOCARE;
  207.                 r_pat[rp++] = '.';
  208.                 r_pat[rp++] = '*';
  209.                 break; 
  210.             }
  211.             Pattern[j++] = WILDCD;
  212.             break; 
  213.         case '(':  
  214.             Pattern[j++] = LPARENT; 
  215.             r_pat[rp++] = '(';     
  216.             break;
  217.         case ')':  
  218.             Pattern[j++] = RPARENT; 
  219.             r_pat[rp++] = ')'; 
  220.             break;
  221.         case '[':  
  222.             Pattern[j++] = LRANGE;  
  223.             r_pat[rp++] = '[';
  224.             IN_RANGE = ON;
  225.             break;
  226.         case ']':  
  227.             Pattern[j++] = RRANGE;  
  228.             r_pat[rp++] = ']'; 
  229.             IN_RANGE = OFF;
  230.             break;
  231.         case '<':  
  232.             Pattern[j++] = LANGLE;  
  233.             break;
  234.         case '>':  
  235.             Pattern[j++] = RANGLE;  
  236.             break;
  237.         case '^':  
  238.             if (temp[i-1] == '[') Pattern[j++] = NOTSYM;
  239.             else Pattern[j++] = '\n';
  240.             r_pat[rp++] = '^';
  241.             break;
  242.         case '$':  
  243.             Pattern[j++] = '\n'; 
  244.             r_pat[rp++] = '$';
  245.             break;
  246.         case '.':  
  247.             Pattern[j++] = NOCARE;
  248.             r_pat[rp++] = '.';
  249.             break;
  250.         case '*':  
  251.             Pattern[j++] = STAR; 
  252.             r_pat[rp++] = '*';
  253.             break;
  254.         case '|':  
  255.             Pattern[j++] = ORSYM; 
  256.             r_pat[rp++] = '|';
  257.             break;
  258.         case ',':  
  259.             Pattern[j++] = ORPAT;  
  260.             RE_ERR = ON; 
  261.             break;
  262.         case ';':  
  263.             if(ANDON) RE_ERR = ON; 
  264.             Pattern[j++] = ANDPAT;
  265.             ANDON = ON;
  266.             break;
  267.         case '-':  
  268.             if(IN_RANGE) {
  269.                 Pattern[j++] = HYPHEN; 
  270.                 r_pat[rp++] = '-';
  271.             }
  272.             else { 
  273.                 Pattern[j++] = temp[i];
  274.                 r_pat[rp++] = temp[i];
  275.             }  
  276.             break;
  277.         case NNLINE :
  278.             Pattern[j++] = temp[i];
  279.             r_pat[rp++] = 'N';
  280.             break;
  281.         default:   
  282.             Pattern[j++] = temp[i]; 
  283.             r_pat[rp++] = temp[i];
  284.             break;
  285.         }
  286.     }
  287.     if(REGEX) {           /* append ').' at end of regular expression */
  288.         r_pat[rp++] = ')';
  289.         r_pat[rp++] = '.';
  290.         Pattern[j++] = NOCARE;
  291.         TAIL = ON;
  292.     }
  293.     Pattern[j] = '\0'; 
  294.     m = j;
  295.     r_pat[rp] = '\0'; 
  296.     if(REGEX)
  297.     {  
  298.         if(DELIMITER || WORDBOUND)  {
  299.             fprintf(stderr, "%s: -d or -w option is not supported for this pattern\n", Progname);
  300.             free(r_pat);
  301.             if (!EXITONERROR) {
  302.                 errno = 2;
  303.                 return -1;
  304.             }
  305.             else exit(2);
  306.         }
  307.         if(RE_ERR) {
  308.             fprintf(stderr, "%s: illegal regular expression\n", Progname);
  309.             free(r_pat);
  310.             if (!EXITONERROR) {
  311.                 errno = 2;
  312.                 return -1;
  313.             }
  314.             else exit(2);
  315.         }
  316.         while(*Pattern != NOCARE && m-- > 0) Pattern++;  /* poit to . */
  317.         num_pos = init(r_pat, table);
  318.         if(num_pos <= 0) {
  319.             fprintf(stderr, "%s: illegal regular expression\n", Progname);
  320.             free(r_pat);
  321.             if (!EXITONERROR) {
  322.                 errno = 2;
  323.                 return -1;
  324.             }
  325.             else exit(2);
  326.         }
  327.         if(num_pos > 30) {
  328.             fprintf(stderr, "%s: regular expression too long\n", Progname);
  329.             free(r_pat);
  330.             if (!EXITONERROR) {
  331.                 errno = 2;
  332.                 return -1;
  333.             }
  334.             else exit(2);
  335.         }
  336.         strcpy(old_pat, Pattern); /* do real change to the Pattern to be returned */
  337.         free(r_pat);
  338.         return 0;
  339.     } /* if regex */
  340.  
  341.     free(r_pat);
  342.     return 0;
  343. }
  344.  
  345.